/**
 * 
 */
package thulearningcore;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import thulearningcore.util.TLNullConverter;

/**
 * @author Nostalgia
 * 
 */
public abstract class CourseDetailInfo implements Cloneable {

	protected String courseID;

	protected String title;
	protected String detail;
	protected String detailURL;

	protected boolean detailLoaded;

	protected boolean updated;

	protected static final String baseURL = LearningManager.getBaseAddress();//"https://learn.tsinghua.edu.cn";
	protected static final String nullFlag = "\0";

	protected CourseDetailInfo() {
		this(null, null, null);
	}

	/**
	 * @param title
	 * @param detailURL
	 */
	protected CourseDetailInfo(String courseID, String title, String detailURL) {
		this(courseID, title, detailURL, null, false);
	}

	protected CourseDetailInfo(String courseID, String title, String detailURL,
			String detail) {
		this(courseID, title, detailURL, detail, false);
	}

	protected CourseDetailInfo(String courseID, String title, String detailURL,
			String detail, boolean updated) {
		super();
		this.courseID = courseID;

		this.title = title;
		this.detail = null;
		this.detailURL = detailURL;

		this.detailLoaded = false;

		this.updated = updated;
	}

	public String getCourseID() {
		return courseID;
	}

	public void setCourseID(String courseID) {
		this.courseID = courseID;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getDetail() {
		return detail;
	}

	public boolean isDetailLoaded() {
		if (this.detail == null) {
			this.detailLoaded = false;
		}
		return this.detailLoaded;
	}

	public void setDetail(String detail) {
		this.setDetail(detail, false);
	}

	public void setDetail(String detail, boolean updated) {
		this.detail = detail;
		this.detailLoaded = detail != null;
		this.updated = this.updated || updated;
	}

	public String getDetailURL() {
		return detailURL;
	}

	public void setDetailURL(String detailURL) {
		this.detailURL = detailURL;
	}

	public boolean isUpdated() {
		return this.updated;
	}

	public void setUpdated(boolean updated) {
		this.updated = updated;
	}
	
	public void markAsRead() {
		this.updated = false;
	}

	/**
	 * Load detail info from detail URL
	 * 
	 * @return whether load is succeeded
	 */
	synchronized protected boolean loadDetail() {
		return false;
	}

	synchronized protected boolean checkUpdate(
			ArrayList<? extends CourseDetailInfo> cache) {
		return this.updated |= !cache.contains(this);
	}

	public void writeData(DataOutputStream dos) throws IOException {
		dos.writeUTF(TLNullConverter.convert(this.courseID));
		dos.writeUTF(TLNullConverter.convert(this.detailURL));
		dos.writeUTF(TLNullConverter.convert(this.title));

		dos.writeUTF(TLNullConverter.convert(this.detail));

		dos.writeBoolean(this.detailLoaded);
		dos.writeBoolean(this.updated);

	}

	public CourseDetailInfo readData(DataInputStream dis) throws IOException {
		this.courseID = TLNullConverter.revert(dis.readUTF());
		this.detailURL = TLNullConverter.revert(dis.readUTF());
		this.title = TLNullConverter.revert(dis.readUTF());

		this.detail = TLNullConverter.revert(dis.readUTF());

		this.detailLoaded = dis.readBoolean();
		this.updated = dis.readBoolean();
		return this;
	}

	/*
	 * not used,all packaged to TLURLConnection
	 * 
	 * protected String post(String addr) throws IOException { return post(addr,
	 * "utf-8"); }
	 * 
	 * protected String post(String addr, String charset) throws IOException {
	 * URL url = new URL(addr);
	 * 
	 * HttpURLConnection httpc = (HttpURLConnection) url.openConnection();
	 * httpc.addRequestProperty("Cookie", TLCookieManager.getInstance()
	 * .getCookies());
	 * 
	 * InputStreamReader reader = new InputStreamReader( httpc.getInputStream(),
	 * charset); BufferedReader breader = new BufferedReader(reader, 8192);
	 * 
	 * StringBuilder sb = new StringBuilder(4096); CharBuffer charBuffer =
	 * CharBuffer.allocate(4096); while (breader.read(charBuffer) != -1) { if
	 * (charBuffer.length() == 0) { charBuffer.flip(); sb.append(charBuffer); }
	 * } charBuffer.flip(); sb.append(charBuffer); String result =
	 * sb.toString();
	 * 
	 * breader.close(); reader.close(); return result; }
	 */

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((courseID == null) ? 0 : courseID.hashCode());
		result = prime * result + ((detail == null) ? 0 : detail.hashCode());
		result = prime * result
				+ ((detailURL == null) ? 0 : detailURL.hashCode());
		result = prime * result + ((title == null) ? 0 : title.hashCode());
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		CourseDetailInfo other = (CourseDetailInfo) obj;
		if (courseID == null) {
			if (other.courseID != null)
				return false;
		} else if (!courseID.equals(other.courseID))
			return false;
		if (title == null) {
			if (other.title != null)
				return false;
		} else if (!title.equals(other.title))
			return false;
		return true;
	}

	public CourseDetailInfo clone() throws CloneNotSupportedException {
		return (CourseDetailInfo) super.clone();
	}

}
